package com.example.testwebrtc;

import android.util.Log;

import org.json.JSONObject;

import java.io.InputStream;
import java.net.URISyntaxException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import io.socket.engineio.client.EngineIOException;
import okhttp3.OkHttpClient;

public class SignalClient {

    private static SignalClient mInstance;
    private OnSignalEventListener mOnSignalEventListener;

    private Socket mSocket;

    public Socket getmSocket() {
        return mSocket;
    }

    private String mRoomName;
    //信令服务器事件
    public interface OnSignalEventListener {
        void onConnected();
        void onConnecting();
        void onDisconnected();
        void onUserJoined(String roomName, String userID);
        void onUserLeaved(String roomName, String userID);
        void onRemoteUserJoined(String roomName);
        void onRemoteUserLeaved(String roomName, String userID);
        void onRoomFull(String roomName, String userID);
        void onMessage(String message);
    }
    //单例
    public static SignalClient getInstance() {
        synchronized (SignalClient.class) {
            if (mInstance == null) {
                mInstance = new SignalClient();
            }
        }
        return mInstance;
    }

    //自签署证书
    public static void init(InputStream is){
        try {
            //设置https证书  cer服务器导出的
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            Certificate cer = cf.generateCertificate(is);

            //把证书设置到证书库
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            keyStore.setCertificateEntry("as", cer);

            //信任管理
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                    TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            X509TrustManager userTrustManager = (X509TrustManager) trustManagers[0];
            SSLContext  sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null,new TrustManager[]{userTrustManager},new SecureRandom());
            SSLSocketFactory socketFactory = sslContext.getSocketFactory();
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .sslSocketFactory(socketFactory, userTrustManager)
                    .hostnameVerifier(new HostnameVerifier() {
                        @Override
                        public boolean verify(String hostname, SSLSession session) {
                            //在这里验证是否为可信任客户端
                            return true;
                        }
                    })
                    .build();
            //使用自定义的okHttpClient
            IO.setDefaultOkHttpCallFactory(okHttpClient);
            IO.setDefaultOkHttpWebSocketFactory(okHttpClient);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private SignalClient() {
    }

    public void setSignalEventListener(final OnSignalEventListener listener) {
        mOnSignalEventListener = listener;
    }
    //向服务器发送join消息
    public void joinRoom(String url, String roomName) {
        Log.i("zcwfeng", "joinRoom: " + url + ", " + roomName);
        try {
            //连接服务器
            mSocket = IO.socket(url);
            mSocket.connect();
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return;
        }
        //mUserId = userId;
        mRoomName = roomName;
        //绑定收消息的监听
        listenSignalEvents();

        mSocket.emit("join", mRoomName);
    }
    //向服务器发送leave消息
    public void leaveRoom() {
        if (mSocket == null) {
            return;
        }
        mSocket.emit("leave", mRoomName);
        mSocket.close();
        mSocket = null;
    }

    //向房间发送信息
    public void sendMessage(JSONObject message) {

        if (mSocket == null) {
            return;
        }
        mSocket.emit("message", mRoomName, message);
    }

    //侦听从服务器收到的消息
    private void listenSignalEvents() {

        if (mSocket == null) {
            return;
        }

        mSocket.on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                System.out.println("server error");
                EngineIOException e = (EngineIOException) args[0];
                e.printStackTrace();
            }
        });
        //连接服务器成功
        mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                String sessionId = mSocket.id();
//                Log.i("zcwfeng", "onConnected");
                System.out.println("EVENT_CONNECT");
                if (mOnSignalEventListener != null) {
                    mOnSignalEventListener.onConnected();
                }
            }
        });
        //连接中
        mSocket.on(Socket.EVENT_CONNECTING, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
//                Log.i("zcwfeng", "onConnecting");
                if (mOnSignalEventListener != null) {
                    mOnSignalEventListener.onConnecting();
                }
            }
        });
        //断开与服务器的连接
        mSocket.on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.i("zcwfeng", "onDisconnected");
                if (mOnSignalEventListener != null) {
                    mOnSignalEventListener.onDisconnected();
                }
            }
        });

        //加入房间
        mSocket.on("joined", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                String roomName = (String) args[0];
                String userId = (String) args[1];
                if (/*!mUserId.equals(userId) &&*/ mOnSignalEventListener != null) {
                    //mOnSignalEventListener.onRemoteUserJoined(userId);
                    mOnSignalEventListener.onUserJoined(roomName, userId);
                }
                //Log.i(TAG, "onRemoteUserJoined: " + userId);
//                Log.i("zcwfeng", "onUserJoined, room:" + roomName + "uid:" + userId);
//                System.out.println("joined    "+roomName+"  "+userId);
//                mSocket.emit("message","666666");
            }
        });
        //离开房间
        mSocket.on("leaved", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                String roomName = (String) args[0];
                String userId = (String) args[1];
                if (/*!mUserId.equals(userId) &&*/ mOnSignalEventListener != null) {
                    //mOnSignalEventListener.onRemoteUserLeft(userId);
                    mOnSignalEventListener.onUserLeaved(roomName, userId);
                }
                Log.i("zcwfeng", "onUserLeaved, room:" + roomName + "uid:" + userId);
            }
        });
        //其它用户加入
        mSocket.on("otherjoin", new Emitter.Listener() {

            @Override
            public void call(Object... args) {
                String roomName = (String) args[0];
                String userId = (String) args[1];
                if (mOnSignalEventListener != null) {
                    mOnSignalEventListener.onRemoteUserJoined(roomName);
                }
                Log.i("zcwfeng", "onRemoteUserJoined, room:" + roomName + "uid:" + userId);
            }
        });
        //其它用户离开
        mSocket.on("bye", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                String roomName = (String) args[0];
                String userId = (String) args[1];
                if (mOnSignalEventListener != null) {
                    mOnSignalEventListener.onRemoteUserLeaved(roomName, userId);
                }
                Log.i("zcwfeng", "onRemoteUserLeaved, room:" + roomName + "uid:" + userId);

            }
        });
        //房满
        mSocket.on("full", new Emitter.Listener() {
            @Override
            public void call(Object... args) {

                //释放资源
                mSocket.disconnect();
                mSocket.close();
                mSocket = null;

                String roomName = (String) args[0];
                String userId = (String) args[1];

                if (mOnSignalEventListener != null) {
                    mOnSignalEventListener.onRoomFull(roomName, userId);
                }

                Log.i("zcwfeng", "onRoomFull, room:" + roomName + "uid:" + userId);

            }
        });
        //发送消息
        mSocket.on("message", new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                String roomName = (String)args[0];
                String msg = (String) args[2];

                if (mOnSignalEventListener != null) {
                    mOnSignalEventListener.onMessage(msg);
                }

                Log.i("zcwfeng", "onMessage, room:" + roomName + "data:" + msg);

            }
        });
    }
}
